home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / LAPB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-12  |  15.5 KB  |  656 lines

  1. /* Link Access Procedures Balanced (LAPB) - with changes for rational
  2.  * behavior over packet radio
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "timer.h"
  7. #include "ax25.h"
  8. #include "lapb.h"
  9.  
  10. extern int32 Clock;
  11. extern int32 Axirtt;
  12. int16 ftype();
  13. void lapbstate();
  14. int ip_route();
  15. static void handleit(),procdata();
  16. static int ackours();
  17.  
  18. /* Process incoming frames */
  19. int
  20. lapb_input(axp,cmdrsp,bp)
  21. struct ax25_cb *axp;        /* Link control structure */
  22. char cmdrsp;            /* Command/response flag */
  23. struct mbuf *bp;        /* Rest of frame, starting with ctl */
  24. {
  25.     char control;
  26.     char class;        /* General class (I/S/U) of frame */
  27.     int16 type;        /* Specific type (I/RR/RNR/etc) of frame */
  28.     char pf;        /* extracted poll/final bit */
  29.     char poll = 0;
  30.     char final = 0;
  31.     int nr;            /* ACK number of incoming frame */
  32.     int ns;            /* Seq number of incoming frame */
  33.     char tmp;
  34.  
  35.     if(bp == NULLBUF || axp == NULLAX25){
  36.         free_p(bp);
  37.         return -1;
  38.     }
  39.  
  40.     /* Extract the various parts of the control field for easy use */
  41.     control = pullchar(&bp);
  42.     type = ftype(control);
  43.     class = type & 0x3;
  44.     pf = control & PF;
  45.     /* Check for polls and finals */
  46.     if(pf){
  47.         switch(cmdrsp){
  48.         case COMMAND:
  49.             poll = YES;
  50.             break;
  51.         case RESPONSE:
  52.             final = YES;
  53.             break;
  54.         }
  55.     }
  56.     /* Extract sequence numbers, if present */
  57.     switch(class){
  58.     case I:
  59.     case I+2:
  60.         ns = (control >> 1) & MMASK;
  61.     case S:    /* Note fall-thru */
  62.         nr = (control >> 5) & MMASK;
  63.         break;
  64.     }
  65.     /* This section follows the SDL diagrams by K3NA fairly closely */
  66.     switch(axp->state){
  67.     case DISCONNECTED:
  68.         switch(type){
  69.         case SABM:    /* Initialize or reset link */
  70.             sendctl(axp,RESPONSE,UA|pf);    /* Always accept */
  71.             clr_ex(axp);
  72.             axp->unack = axp->vr = axp->vs = 0;
  73.             lapbstate(axp,CONNECTED);/* Resets state counters */
  74.             axp->srt = Axirtt;
  75.             axp->t1.start = 2*axp->srt;
  76.             start_timer(&axp->t3);
  77.             break;
  78.         case DM:    /* Ignore to avoid infinite loops */
  79.             break;
  80.         default:    /* All others get DM */
  81.             if(poll)
  82.                 sendctl(axp,RESPONSE,DM|pf);
  83.             break;
  84.         }
  85.         break;
  86.     case SETUP:
  87.         switch(type){
  88.         case SABM:    /* Simultaneous open */
  89.             sendctl(axp,RESPONSE,UA|pf);
  90.             break;
  91.         case DISC:
  92.             sendctl(axp,RESPONSE,DM|pf);
  93.             break;
  94.         case UA:    /* Connection accepted */
  95.             /* Note: xmit queue not cleared */
  96.             stop_timer(&axp->t1);
  97.             start_timer(&axp->t3);
  98.             axp->unack = axp->vr = axp->vs = 0;
  99.             lapbstate(axp,CONNECTED);
  100.             break;            
  101.         case DM:    /* Connection refused */
  102.             free_q(&axp->txq);
  103.             stop_timer(&axp->t1);
  104.             axp->reason = LB_DM;
  105.             lapbstate(axp,DISCONNECTED);
  106.             break;
  107.         default:    /* All other frames ignored */
  108.             break;
  109.         }
  110.         break;
  111.     case DISCPENDING:
  112.         switch(type){
  113.         case SABM:
  114.             sendctl(axp,RESPONSE,DM|pf);
  115.             break;
  116.         case DISC:
  117.             sendctl(axp,RESPONSE,UA|pf);
  118.             break;
  119.         case UA:
  120.         case DM:
  121.             stop_timer(&axp->t1);
  122.             lapbstate(axp,DISCONNECTED);
  123.             break;
  124.         default:    /* Respond with DM only to command polls */
  125.             if(poll)
  126.                 sendctl(axp,RESPONSE,DM|pf);
  127.             break;
  128.         }
  129.         break;
  130.     case CONNECTED:
  131.         switch(type){
  132.         case SABM:
  133.             sendctl(axp,RESPONSE,UA|pf);
  134.             clr_ex(axp);
  135.             free_q(&axp->txq);
  136.             stop_timer(&axp->t1);
  137.             start_timer(&axp->t3);
  138.             axp->unack = axp->vr = axp->vs = 0;
  139.             lapbstate(axp,CONNECTED); /* Purge queues */
  140.             break;
  141.         case DISC:
  142.             free_q(&axp->txq);
  143.             sendctl(axp,RESPONSE,UA|pf);
  144.             stop_timer(&axp->t1);
  145.             stop_timer(&axp->t3);
  146.             axp->reason = LB_NORMAL;
  147.             lapbstate(axp,DISCONNECTED);
  148.             break;
  149.         case DM:
  150.             axp->reason = LB_DM;
  151.             lapbstate(axp,DISCONNECTED);
  152.             break;
  153.         case UA:
  154.             est_link(axp);
  155.             lapbstate(axp,SETUP);    /* Re-establish */    
  156.             break;            
  157.         case FRMR:
  158.             est_link(axp);
  159.             lapbstate(axp,SETUP);    /* Re-establish link */
  160.             break;
  161.         case RR:
  162.         case RNR:
  163.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  164.             if(poll)
  165.                 enq_resp(axp);
  166.             ackours(axp,nr);
  167.             break;
  168.         case REJ:
  169.             axp->flags.remotebusy = NO;
  170.             if(poll)
  171.                 enq_resp(axp);
  172.             ackours(axp,nr);
  173.             stop_timer(&axp->t1);
  174.             start_timer(&axp->t3);
  175.             /* This may or may not actually invoke transmission,
  176.              * depending on whether this REJ was caused by
  177.              * our losing his prior ACK.
  178.              */
  179.             inv_rex(axp);
  180.             break;    
  181.         case I:
  182.             ackours(axp,nr); /** == -1) */
  183.             if(len_mbuf(axp->rxq) >= axp->window){
  184.                 /* Too bad he didn't listen to us; he'll
  185.                  * have to resend the frame later. This
  186.                  * drastic action is necessary to avoid
  187.                  * deadlock.
  188.                  */
  189.                 if(poll)
  190.                     sendctl(axp,RESPONSE,RNR|pf);
  191.                 free_p(bp);
  192.                 bp = NULLBUF;
  193.                 break;
  194.             }
  195.             /* Reject or ignore I-frames with receive sequence number errors */
  196.             if(ns != axp->vr){
  197.                 if(axp->proto == V1 || !axp->flags.rejsent){
  198.                     axp->flags.rejsent = YES;
  199.                     sendctl(axp,RESPONSE,REJ | pf);
  200.                 } else if(poll)
  201.                     enq_resp(axp);
  202.                 axp->response = 0;
  203.                 break;
  204.             }
  205.             axp->flags.rejsent = NO;
  206.             axp->vr = (axp->vr+1) & MMASK;
  207.             tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  208.             if(poll){
  209.                 sendctl(axp,RESPONSE,tmp|PF);
  210.             } else {
  211.                 axp->response = tmp;
  212.             }
  213.             procdata(axp,bp);
  214.             bp = NULLBUF;
  215.             break;
  216.         default:    /* All others ignored */
  217.             break;
  218.         }
  219.         break;
  220.     case RECOVERY:
  221.         switch(type){
  222.         case SABM:
  223.             sendctl(axp,RESPONSE,UA|pf);
  224.             clr_ex(axp);
  225.             stop_timer(&axp->t1);
  226.             start_timer(&axp->t3);
  227.             axp->unack = axp->vr = axp->vs = 0;
  228.             lapbstate(axp,CONNECTED); /* Purge queues */
  229.             break;
  230.         case DISC:
  231.             free_q(&axp->txq);
  232.             sendctl(axp,RESPONSE,UA|pf);
  233.             stop_timer(&axp->t1);
  234.             stop_timer(&axp->t3);
  235.             axp->response = UA;
  236.             axp->reason = LB_NORMAL;
  237.             lapbstate(axp,DISCONNECTED);
  238.             break;
  239.         case DM:
  240.             axp->reason = LB_DM;
  241.             lapbstate(axp,DISCONNECTED);
  242.             break;
  243.         case UA:
  244.             est_link(axp);
  245.             lapbstate(axp,SETUP);    /* Re-establish */    
  246.             break;
  247.         case FRMR:
  248.             est_link(axp);
  249.             lapbstate(axp,SETUP);    /* Re-establish link */
  250.             break;
  251.         case RR:
  252.         case RNR:
  253.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  254.             if(axp->proto == V1 || final){
  255.                 stop_timer(&axp->t1);
  256.                 ackours(axp,nr);
  257.                 if(axp->unack != 0){
  258.                     inv_rex(axp);
  259.                 } else {
  260.                     start_timer(&axp->t3);
  261.                     lapbstate(axp,CONNECTED);
  262.                 }
  263.             } else {
  264.                 if(poll)
  265.                     enq_resp(axp);
  266.                 ackours(axp,nr);
  267.                 /* Keep timer running even if all frames
  268.                  * were acked, since we must see a Final
  269.                  */
  270.                 if(!run_timer(&axp->t1))
  271.                     start_timer(&axp->t1);
  272.             }
  273.             break;
  274.         case REJ:
  275.             axp->flags.remotebusy = NO;
  276.             /* Don't insist on a Final response from the old proto */
  277.             if(axp->proto == V1 || final){
  278.                 stop_timer(&axp->t1);
  279.                 ackours(axp,nr);
  280.                 if(axp->unack != 0){
  281.                     inv_rex(axp);
  282.                 } else {
  283.                     start_timer(&axp->t3);
  284.                     lapbstate(axp,CONNECTED);
  285.                 }
  286.             } else {
  287.                 if(poll)
  288.                     enq_resp(axp);
  289.                 ackours(axp,nr);
  290.                 if(axp->unack != 0){
  291.                     /* This is certain to trigger output */
  292.                     inv_rex(axp);
  293.                 }
  294.                 /* A REJ that acks everything but doesn't
  295.                  * have the F bit set can cause a deadlock.
  296.                  * So make sure the timer is running.
  297.                  */
  298.                 if(!run_timer(&axp->t1))
  299.                     start_timer(&axp->t1);
  300.             }
  301.             break;
  302.         case I:
  303.             ackours(axp,nr); /** == -1) */
  304.             /* Make sure timer is running, since an I frame
  305.              * cannot satisfy a poll
  306.              */
  307.             if(!run_timer(&axp->t1))
  308.                 start_timer(&axp->t1);
  309.             if(len_mbuf(axp->rxq) >= axp->window){
  310.                 /* Too bad he didn't listen to us; he'll
  311.                  * have to resend the frame later. This
  312.                  * drastic action is necessary to avoid
  313.                  * memory deadlock.
  314.                  */
  315.                 sendctl(axp,RESPONSE,RNR | pf);
  316.                 free_p(bp);
  317.                 bp = NULLBUF;
  318.                 break;
  319.             }
  320.             /* Reject or ignore I-frames with receive sequence number errors */
  321.             if(ns != axp->vr){
  322.                 if(axp->proto == V1 || !axp->flags.rejsent){
  323.                     axp->flags.rejsent = YES;
  324.                     sendctl(axp,RESPONSE,REJ | pf);
  325.                 } else if(poll)
  326.                     enq_resp(axp);
  327.  
  328.                 axp->response = 0;
  329.                 break;
  330.             }
  331.             axp->flags.rejsent = NO;
  332.             axp->vr = (axp->vr+1) & MMASK;
  333.             tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  334.             if(poll){
  335.                 sendctl(axp,RESPONSE,tmp|PF);
  336.             } else {
  337.                 axp->response = tmp;
  338.             }
  339.             procdata(axp,bp);
  340.             bp = NULLBUF;
  341.             break;
  342.         default:
  343.             break;        /* Ignored */
  344.         }
  345.         break;
  346.     }
  347.     free_p(bp);    /* In case anything's left */
  348.  
  349.     /* See if we can send some data, perhaps piggybacking an ack.
  350.      * If successful, lapb_output will clear axp->response.
  351.      */
  352.     lapb_output(axp);
  353.     if(axp->response != 0){
  354.         sendctl(axp,RESPONSE,axp->response);
  355.         axp->response = 0;
  356.     }
  357.     return 0;
  358. }
  359. /* Handle incoming acknowledgements for frames we've sent.
  360.  * Free frames being acknowledged.
  361.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  362.  */
  363. static int
  364. ackours(axp,n)
  365. struct ax25_cb *axp;
  366. char n;
  367. {    
  368.     struct mbuf *bp;
  369.     int acked = 0;    /* Count of frames acked by this ACK */
  370.     int oldest;    /* Seq number of oldest unacked I-frame */
  371.  
  372.     /* Free up acknowledged frames by purging frames from the I-frame
  373.      * transmit queue. Start at the remote end's last reported V(r)
  374.      * and keep going until we reach the new sequence number.
  375.      * If we try to free a null pointer,
  376.      * then we have a frame reject condition.
  377.      */
  378.     oldest = (axp->vs - axp->unack) & MMASK;
  379.     while(axp->unack != 0 && oldest != n){
  380.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  381.             /* Acking unsent frame */
  382.             return -1;
  383.         }
  384.         free_p(bp);
  385.         axp->unack--;
  386.         acked++;
  387.         if(axp->flags.rtt_run && axp->rtt_seq == oldest){
  388.             /* A frame being timed has been acked */
  389.             axp->flags.rtt_run = 0;
  390.             /* Update only if frame wasn't retransmitted */
  391.             if(!axp->flags.retrans)
  392.                 axp->srt = ((axp->srt * 7) +
  393.                  (Clock - axp->rtt_time)) >> 3;
  394.         }
  395.         axp->flags.retrans = 0;
  396.         axp->retries = 0;
  397.         oldest = (oldest + 1) & MMASK;
  398.     }
  399.     if(axp->unack == 0){
  400.         /* All frames acked, stop timeout */
  401.         stop_timer(&axp->t1);
  402.         start_timer(&axp->t3);
  403.     } else if(acked != 0) { 
  404.         /* Partial ACK; restart timer */
  405.         start_timer(&axp->t1);
  406.     }
  407.     if(acked != 0){
  408.         /* If user has set a transmit upcall, indicate how many frames
  409.          * may be queued
  410.          */
  411.         if(axp->t_upcall != NULLVFP)
  412.             (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  413.     }
  414.     return 0;
  415. }
  416.  
  417. /* Establish data link */
  418. est_link(axp)
  419. struct ax25_cb *axp;
  420. {
  421.     clr_ex(axp);
  422.     axp->retries = 0;
  423.     sendctl(axp,COMMAND,SABM|PF);
  424.     stop_timer(&axp->t3);
  425.     start_timer(&axp->t1);
  426. }
  427. /* Clear exception conditions */
  428. clr_ex(axp)
  429. struct ax25_cb *axp;
  430. {
  431.     axp->flags.remotebusy = NO;
  432.     axp->flags.rejsent = NO;
  433.     axp->response = 0;
  434.     stop_timer(&axp->t3);
  435. }
  436. /* Enquiry response */
  437. enq_resp(axp)
  438. struct ax25_cb *axp;
  439. {
  440.     char ctl;
  441.  
  442.     ctl = len_mbuf(axp->rxq) >= axp->window ? RNR|PF : RR|PF;    
  443.     sendctl(axp,RESPONSE,ctl);
  444.     axp->response = 0;
  445.     stop_timer(&axp->t3);
  446. }
  447. /* Invoke retransmission */
  448. inv_rex(axp)
  449. struct ax25_cb *axp;
  450. {
  451.     axp->vs -= axp->unack;
  452.     axp->vs &= MMASK;
  453.     axp->unack = 0;
  454. }
  455. /* Send S or U frame to currently connected station */
  456. int
  457. sendctl(axp,cmdrsp,cmd)
  458. struct ax25_cb *axp;
  459. char cmdrsp,cmd;
  460. {
  461.     if((ftype(cmd) & 0x3) == S)    /* Insert V(R) if S frame */
  462.         cmd |= (axp->vr << 5);
  463.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  464. }
  465. /* Start data transmission on link, if possible
  466.  * Return number of frames sent
  467.  */
  468. int
  469. lapb_output(axp)
  470. register struct ax25_cb *axp;
  471. {
  472.     register struct mbuf *bp;
  473.     struct mbuf *tbp;
  474.     char control;
  475.     int sent = 0;
  476.     int i;
  477.  
  478.     if(axp == NULLAX25
  479.      || (axp->state != RECOVERY && axp->state != CONNECTED)
  480.      || axp->flags.remotebusy)
  481.         return 0;
  482.  
  483.     /* Dig into the send queue for the first unsent frame */
  484.     bp = axp->txq;
  485.     for(i = 0; i < axp->unack; i++){
  486.         if(bp == NULLBUF)
  487.             break;    /* Nothing to do */
  488.         bp = bp->anext;
  489.     }
  490.     /* Start at first unsent I-frame, stop when either the
  491.      * number of unacknowledged frames reaches the maxframe limit,
  492.      * or when there are no more frames to send
  493.      */
  494.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  495.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  496.         axp->vs &= MMASK;
  497.         dup_p(&tbp,bp,0,len_mbuf(bp));
  498.         if(tbp == NULLBUF)
  499.             return sent;    /* Probably out of memory */
  500.         sendframe(axp,COMMAND,control,tbp);
  501.         axp->unack++;
  502.         /* We're implicitly acking any data he's sent, so stop any
  503.          * delayed ack
  504.          */
  505.         axp->response = 0;
  506.         /* Use clamped backoff algorithm */
  507.         if(!axp->flags.retrans)
  508.             axp->t1.start = 2 * (axp->srt << axp->retries);
  509.         if(!run_timer(&axp->t1)){
  510.             stop_timer(&axp->t3);
  511.             start_timer(&axp->t1);
  512.         }
  513.         sent++;
  514.         bp = bp->anext;
  515.         if(!axp->flags.rtt_run){
  516.             /* Start round trip timer */
  517.             axp->rtt_seq = (control >> 1) & MMASK;
  518.             axp->rtt_time = Clock;
  519.             axp->flags.rtt_run = 1;
  520.         }
  521.     }
  522.     return sent;
  523. }
  524. /* Set new link state */
  525. void
  526. lapbstate(axp,s)
  527. struct ax25_cb *axp;
  528. int s;
  529. {
  530.     int oldstate;
  531.  
  532.     oldstate = axp->state;
  533.     axp->state = s;
  534.     if(s == DISCONNECTED){
  535.         stop_timer(&axp->t1);
  536.         stop_timer(&axp->t3);
  537.         free_q(&axp->txq);
  538.     }
  539.     /* Don't bother the client unless the state is really changing */
  540.     if(oldstate != s && axp->s_upcall != NULLVFP)
  541.         (*axp->s_upcall)(axp,oldstate,s);
  542. }
  543. /* Process a valid incoming I frame */
  544. static void
  545. procdata(axp,bp)
  546. struct ax25_cb *axp;
  547. struct mbuf *bp;
  548. {
  549.     char pid;
  550.     char seq;
  551.  
  552.     /* Extract level 3 PID */
  553.     if(pullup(&bp,&pid,1) != 1)
  554.         return;    /* No PID */
  555.  
  556.     if(axp->segremain != 0){
  557.         /* Reassembly in progress; continue */
  558.         pullup(&bp,&seq,1);
  559.         if(uchar(pid) == PID_SEGMENT
  560.          && (seq & SEG_REM) == axp->segremain - 1){
  561.             /* Correct, in-order segment */
  562.             append(&axp->rxasm,bp);
  563.             if((axp->segremain = (seq & SEG_REM)) == 0){
  564.                 /* Done; kick it upstairs */
  565.                 pullup(&bp,&pid,1);
  566.                 handleit(axp,pid,axp->rxasm);
  567.                 axp->rxasm = NULLBUF;
  568.             }
  569.         } else {
  570.             /* Error! */
  571.             free_p(axp->rxasm);
  572.             axp->rxasm = NULLBUF;
  573.             axp->segremain = 0;
  574.             free_p(bp);
  575.         }
  576.     } else {
  577.         /* No reassembly in progress */
  578.         if(uchar(pid) == PID_SEGMENT){
  579.             /* Start reassembly */
  580.             pullup(&bp,&seq,1);
  581.             if(!(seq & SEG_FIRST)){
  582.                 free_p(bp);    /* not first seg - error! */
  583.             } else {
  584.                 /* Put first segment on list */
  585.                 axp->segremain = seq & SEG_REM;
  586.                 axp->rxasm = bp;
  587.             }
  588.         } else {
  589.             /* Normal frame; send upstairs */
  590.             handleit(axp,pid,bp);
  591.         }
  592.     }
  593. }
  594. /* New-style frame segmenter. Returns queue of segmented fragments, or
  595.  * original packet if small enough
  596.  */
  597. struct mbuf *
  598. segmenter(bp,ssize)
  599. struct mbuf *bp;    /* Complete packet */
  600. int16 ssize;        /* Max size of frame segments */
  601. {
  602.     struct mbuf *result;
  603.     struct mbuf *bp1;
  604.     int16 len;
  605.     int segments;
  606.  
  607.     len = len_mbuf(bp);
  608.     segments = (len - 1) / ssize;
  609.     if(segments == 0)
  610.         return bp;    /* No segmentation needed */
  611.  
  612.     ssize = min(ssize,len);
  613.     result = alloc_mbuf(ssize + 2);
  614.     result->cnt = ssize + 2;
  615.     result->data[0] = PID_SEGMENT;
  616.     result->data[1] = SEG_FIRST | segments--;
  617.     len -= pullup(&bp,&result->data[2],ssize);
  618.  
  619.     bp1 = result;
  620.     while(segments != 0 && len != 0){
  621.         ssize = min(ssize,len);
  622.         bp1->anext = alloc_mbuf(ssize+2);
  623.         bp1 = bp1->anext;
  624.         bp1->cnt = ssize+2;
  625.         bp1->data[0] = PID_SEGMENT;
  626.         bp1->data[1] = segments--;
  627.         len -= pullup(&bp,&bp1->data[2],ssize);
  628.     }
  629.     return result;
  630. }
  631.  
  632. static void
  633. handleit(axp,pid,bp)
  634. struct ax25_cb *axp;
  635. char pid;
  636. struct mbuf *bp;
  637. {
  638.     switch(uchar(pid)){
  639.     case PID_IP:        /* DoD Internet Protocol */
  640.         ip_route(bp,0);
  641.         break;
  642.     case PID_NO_L3:        /* Enqueue for application */
  643.         append(&axp->rxq,bp);
  644.         if(axp->r_upcall != NULLVFP)
  645.             (*axp->r_upcall)(axp,len_mbuf(axp->rxq));
  646.         break;    
  647.     case PID_NETROM:
  648.         nr_route(bp,axp);
  649.         break;
  650.     default:        /* Note: ARP is invalid here */    
  651.         free_p(bp);
  652.         break;            
  653.     }
  654. }
  655.  
  656.